package com.cremamobile.filemanager.file;

import java.io.File;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.Date;
import java.util.List;

import com.cremamobile.filemanager.file.Exception.ExistSameFileNameException;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.os.Environment;
import android.os.StatFs;
import android.util.Log;


public class FileUtils {

	public static long getSize(File file) {
		if (file ==  null || file.exists())
			return 0;
		if (file.isDirectory()) {
			long sum = 0;
    		File[] children = file.listFiles();
    		for (File child : children) {
    			sum += child.length();
    		}
    		
    		return sum;
		} else {
			return file.length();
		}
	}
	
	public static String name(File file) {
		if (file ==  null || file.exists())
			return null;
		return file.getName();
	}
	
	public static String getExt(File file) {
		if (file ==  null || file.exists())
			return null;
		
		String name = file.getName();
		int pos = name.lastIndexOf( "." );
		if (pos > 0) {
			return name.substring( pos + 1 );
		}
		return null;
	}
	
	public static String getExt(String name) {
		if (name ==  null || name.length() <= 0)
			return null;
		int pos = name.lastIndexOf( "." );
		if (pos > 0) {
			return name.substring( pos + 1 );
		}
		return null;
	}
	
	public static long getLastModified(File file) {
		if (file ==  null || file.exists())
			return 0;
		return file.lastModified();
	}
	
	public static boolean isDir(File file) {
		return file.isDirectory();
	}
	
	public static boolean rename(File file, File new_file) throws ExistSameFileNameException {
		if (file == null || ! file.exists() || new_file == null)
			return false;
		
		if (new_file.exists())
			throw new ExistSameFileNameException(new_file);
		file.renameTo(new_file);
		return true;
	}

	public static boolean rename(String src, String dest) throws ExistSameFileNameException {
		return rename(new File(src), new File(dest));
	}
	
	public static String[] getList(File dir){
        if(dir!=null&&dir.exists())
            return dir.list();
        return null;
    }
	
	public static Bitmap getThumbnail(File file) {
		//TODO.
		return null;
	}
	
	public static long getTotalInternalMemorySize() {
		File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long totalBlocks = stat.getBlockCount();

        return totalBlocks * blockSize;
	}
	
	public static long getAvaiableInternalMemorySize() {
		File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSize();
        long availableBlocks = stat.getAvailableBlocks();

        return availableBlocks * blockSize;

	}
	
	public static long getTotalExternalMemorySize() {
		if (isStorage(true) == true) {
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSize();
            long totalBlocks = stat.getBlockCount();

            return totalBlocks * blockSize;
       } else {
            return -1;
       }
	}
	
	public static void createFolder(String dest) throws ExistSameFileNameException {
		if (dest == null)
			return;
		createFolder(new File(dest));
	}
	
	public static void createFolder(File dest) throws ExistSameFileNameException {
		if (dest.exists()) 
			throw new ExistSameFileNameException(dest);
		dest.mkdir();
	}
	
	
	public static long getAvaiableExternalMemorySize() {
		if (isStorage(true) == true) {
            File path = Environment.getExternalStorageDirectory();
            StatFs stat = new StatFs(path.getPath());
            long blockSize = stat.getBlockSize();
            long availableBlocks = stat.getAvailableBlocks();
            return availableBlocks * blockSize;
        } else {
            return -1;
        }
	}
	
	/** 보기 좋게 MB,KB 단위로 축소시킨다 */
    public static String formatSize(long size) {
         String suffix = null;
 
         long calcuSize = size;
         long reminder = 0;
         if (calcuSize >= 1024) {
             suffix = "KB";
             reminder = calcuSize % 1024;
             calcuSize /= 1024;
             if (calcuSize >= 1024) {
                  suffix = "MB";
                  reminder = calcuSize % 1024;
                  calcuSize /= 1024;
             }
             if (calcuSize >= 1024) {
                 suffix = "GB";
                 reminder = calcuSize % 1024;
                 calcuSize /= 1024;
            }
            if (reminder < 100) {
            	reminder *= 1024;
            }
        }
        StringBuilder resultBuffer = new StringBuilder(Long.toString(calcuSize));
 
        int commaOffset = resultBuffer.length() - 3;
        while (commaOffset > 0) {
             resultBuffer.insert(commaOffset, ',');
             commaOffset -= 3;
        }
 
        if (reminder != 0) {
        	resultBuffer.append(".");
        	resultBuffer.append(String.valueOf(reminder).substring(0, 2));
        }
        
         if (suffix != null) {
              resultBuffer.append(suffix);
         }
 
         return resultBuffer.toString();
    }
    
    /** 외장메모리 sdcard 사용가능한지에 대한 여부 판단 */
    public static boolean isStorage(boolean requireWriteAccess) {
         String state = Environment.getExternalStorageState();
 
          if (Environment.MEDIA_MOUNTED.equals(state)) {
                return true;
          } else if (!requireWriteAccess &&
               Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
               return true;
          }
          return false;
    }
    
    public static boolean copy(File src, File dest) {
    	if (src.isDirectory() ) {
    		if (!dest.exists()) {
    			dest.mkdir();
    		}
    		
    		String[] childPaths = src.list();
    		for (String child : childPaths) {
    			if (copy(new File(src, child), new File(dest, child)) == false)
    				return false;
    		}
    	} else {
    		try {
		    	InputStream in = new FileInputStream(src);
		        OutputStream out = new FileOutputStream(dest);
		
		        // Transfer bytes from in to out
		        byte[] buf = new byte[1024];
		        int len;
		        while ((len = in.read(buf)) > 0) {
		            out.write(buf, 0, len);
		        }
		        in.close();
		        out.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    			return false;
    		}
    		
    	}
		return true;
    }
    
    public static boolean copy(File src, String dest) {
    	return copy(src, new File(dest));
    }
    
    public static boolean copyFromFileChannel(File src, File dest) throws IOException {
    	
    	if (src.isDirectory()) {
    		if (!dest.exists()) {
    			dest.mkdir();
    		}
    		
    		String[] childPaths = src.list();
    		for (String child : childPaths) {
    			copyFromFileChannel(new File(src, child), new File(dest, child));
    		}
    		
    		return true;
    		
    	} else {
	    	FileInputStream inStream = new FileInputStream(src);
	        FileOutputStream outStream = new FileOutputStream(dest);
	        FileChannel inChannel = inStream.getChannel();
	        FileChannel outChannel = outStream.getChannel();
	        
	        inChannel.transferTo(0, inChannel.size(), outChannel);
	
	        inStream.close();
	        outStream.close();
	        
	        return true;
    	}
    }
    
    public static boolean copyFromBuffedStream(File src, String dest) throws IOException {
		BufferedReader bufReader = null;  
		BufferedWriter bufWriter = null;  
		try {  
			bufReader = new BufferedReader(new FileReader(src));
			bufWriter = new BufferedWriter(new FileWriter(dest));
			
			String data;  
			while ((data = bufReader.readLine()) != null) {  
				bufWriter.write(data);  
			}
		} catch (FileNotFoundException e) {  
				e.printStackTrace();  
				return false;
		} finally {  
			if (bufReader != null)  
				bufReader.close();  
			if (bufWriter != null)  
				bufWriter.close();  
		}
		
		return true;
    }
    
    public static void delete(File src) throws IOException {
    	if (src.isDirectory()) {
    		File[] childs = src.listFiles();
    		for (File child : childs)
    			delete(child);
    	}
        src.delete();
    }
    
    public static void delete(String src) throws IOException {
    	delete(new File(src));
    }
    
    public static void move(File src, File dest) throws IOException {
    	copy(src, dest);
    	delete(src);
    }
    
	public static boolean existFiles(List<FileListEntry> list, String destDir) {
		for (FileListEntry item : list) {
			if (FileUtils.existFile(destDir+"/"+item.getName()))
				return true;
		}
		return false;
	}
	
	public static boolean existFile(String dest) {
		File file = new File(dest);
		if (file != null && file.exists())
			return true;
		
		return false;
	}
	
	public static String getRenameWithExisting(DirFileEntry destDir, FileListEntry file) {
		if (file.isDir()) {
			return getRenameTemporaryDir(destDir.getAbsolutePath(), file.getName());
		} else {
			return getRenameTemporaryFile(destDir.getAbsolutePath(), file.getName(), file.getExt());
		}
	}
	
	public static String getRenameTemporaryFile(String dest, String file, String ext) {
		StringBuffer nameTemp = new StringBuffer(file);
		String fullTemp = dest + "/" + nameTemp + "." + ext;
		while(existFile(fullTemp) ) {
			nameTemp.append(" 1");
			fullTemp = dest + "/" + nameTemp.toString() + "." + ext;
		}
		return fullTemp;
	}
	
	public static String getRenameTemporaryDir(String dest, String target) {
		StringBuffer temp = new StringBuffer(dest);
		temp.append("/");
		temp.append(target);
		while(existFile(temp.toString()) ) {
			temp.append(" 1");
		}
		return temp.toString();
		
	}
	
	public static boolean checkExistFiles(FileListEntry destination, List<FileListEntry> list) {
		String target = null;
		for (FileListEntry entry : list) {
			target = destination.getAbsolutePath() + "/" + entry.getFullName();

			if (existFile(target))
				return true;
		}
		
		return false;
	}
	
	public static IntentFilter getRescanIntentFilter() {
		IntentFilter filter = new IntentFilter();
		filter.addAction(Intent.ACTION_MEDIA_BAD_REMOVAL);
		filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
		filter.addAction(Intent.ACTION_MEDIA_REMOVED);
		filter.addAction(Intent.ACTION_MEDIA_SHARED);
		filter.addDataScheme("file"); 
		return filter;
	}

}
